/* allegro */
#include <allegro.h>

/* standard includes */
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>

/* our own includes */
#include "../include/logger.h"
#include "../include/loadpng.h"

int fps = 0; 
int fpscnt = 0;
void (*current_state)(BITMAP *) = NULL;

#define SC_WIDTH 	800
#define SC_HEIGHT 	600
#define SC_DEPTH 	16

#define M_PI 3.141593f

BITMAP *buffer = NULL;

int do_setup(int argn, char * argv[], int * hwmouse)
{
	if (allegro_init() != 0)
	{
		printf("\nCould not initialize allegro :-(\n\n");
		return 1;
	}

	// Parse the params
	int override_log = 0;
	int fullscreen = GFX_AUTODETECT_WINDOWED;
	for(int I = 0; I < argn; I++)
	{
		if(!strcmp(argv[I], "-l")) override_log = 1;
		else if(!strcmp(argv[I], "-f")) fullscreen = GFX_AUTODETECT_FULLSCREEN;
		else if(!strcmp(argv[I], "--help"))
		{
			printf("Command line options explained: \n\n");
			printf("-f\t- Fullscreen mode\n");
			printf("-l\t- Ignore it if the log can not be created\n");
			printf("\n");
			return 1;
		}
	}

	// Start logging
	if(!strt_log("tedit.txt") && override_log == 0)
	{
		set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
		allegro_message("Unable to create a log file! Pass /l flag"
				" to force the app to ignore this");
		return 1;
	};	

	amazolog("*** STARTUP PROCESS BEGUN ***\n");
	
	amazolog("Installing timer . . . ");
	install_timer(); 	
	amazolog("done\n");
	
	/* set a display mode before installing the mouse so we can test if HW 
	 * cursors are supported (else gfx_capabilities is not set)
	 */
	set_color_depth(SC_DEPTH);
	if (set_gfx_mode(fullscreen, SC_WIDTH, SC_HEIGHT, 0, SC_HEIGHT*2) != 0) {
		if (set_gfx_mode(fullscreen, SC_WIDTH, SC_HEIGHT, 0, 0) != 0) {
			if (set_gfx_mode(GFX_SAFE, SC_WIDTH, SC_HEIGHT, 0, 0) != 0) {
	 			set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
	 			allegro_message("Unable to set any graphic "
	 				"mode\n%s\n", allegro_error);
	 			exit(0);
	 		}
      		}
   	}
	
	amazolog("Installing keyboard and mouse . . . ");
	install_keyboard();  
	install_mouse(); 	// must come after install_timer
	enable_hardware_cursor();
	
	/* generate a mouse cursor Lucasarts style */
	static BITMAP * cursor_bmp = 0;
	cursor_bmp = create_bitmap(80, 16);
   	clear_to_color(cursor_bmp, bitmap_mask_color(screen));
   	textout_ex(cursor_bmp, font, "Click Me!", 0, 0, makecol(255, 0, 0), -1);
   	//for (int i = 0; i<32; i++) {
   	//	if(abs(i - 16) < 3 || i < 10 || i > 32 - 10) continue;	// Empty in the center
      	//	putpixel(cursor_bmp, i, 16, makecol(255, 0, 0));
	//	putpixel(cursor_bmp, 16, i, makecol(255, 0, 0));
	//}
	//putpixel(cursor_bmp, 16, 16, makecol(255, 0, 0));
	//circle(cursor_bmp, 16, 16, 8, makecol(255, 0, 0));
	
   	/* select the custom cursor and set the focus point to the middle of it */
   	set_mouse_sprite(cursor_bmp);
   	set_mouse_sprite_focus(16, 16);

	show_mouse(screen);
	amazolog("done\n");
	
	/* check if HW cursor is supported. Display mode has to be set first */
	if ((*hwmouse = ((gfx_capabilities & GFX_HW_CURSOR) == GFX_HW_CURSOR))) {
   		amazolog("Hardware cursor supported\n");
	} else {
   		LOG_WARN("Hardware cursor NOT supported");
	}
	
	/* Make Allegro aware of PNG file format. */
	amazolog("Registering PNG format . . . ");
    	register_png_file_type();
    	amazolog("done\n");
 
 	/* Set the random seed */
 	srand(time(NULL));;

	return 0;
}

void do_cleanup()
{
	amazolog("*** SHUTDOWN PROCESS BEGUN ***\n");
	
	destroy_bitmap(buffer);
	amazolog("Buffer destroyed\n");
	amazolog("done\nTERMINATING LOG & SHUTTING DOWN\n");
	end_log();	
}


double max_sub_angle = (3*M_PI)/4.0f; 
// trs = thickness reduction speed
#define	TRS	3
int max_size = 8 * TRS;
int max_sub_branch = 7;
int branch_length = 30 ;
	
double orig_len;
double line_len;
	
void draw_dust_particle(BITMAP *bmp, int x, int y, int d)
{
	// (1 - (line_len/orig_len)) = weight from this to next color
	
	#define BROWN_SEGMENTS 2
	
	int base[3] = { 29, 19, 4 };
	int target[3] = { 4, 133, 1 };
	
	// This color
	double weight = 1.0f - ((double)(d*TRS) / ((double)max_size-BROWN_SEGMENTS*TRS));
	if(weight < 0)
		weight = 0;

	
	int r = base[0] + (double)(target[0] - base[0])*weight;
	int g = base[1] + (double)(target[1] - base[1])*weight;
	int b = base[2] + (double)(target[2] - base[2])*weight;
	
	// Next branch color
	double weightb = 1.0f - ((double)((d-1)*TRS) / ((double)max_size -BROWN_SEGMENTS*TRS));
	if(weightb < 0)
		weightb = 0;
	int nr = base[0] + (double)(target[0] - base[0])*weightb;
	int ng = base[1] + (double)(target[1] - base[1])*weightb;
	int nb = base[2] + (double)(target[2] - base[2])*weightb;
	
	// Interpolate
	double sw = (1.0f - (line_len/orig_len));
	line_len--;
	//printf("%f\n", sw);
	//while(!key[KEY_ESC]);
	//while(!key[KEY_SPACE]);
	
	r = r + (((double)nr - (double)r)*sw);
	g = g + (((double)ng - (double)g)*sw);
	b = b + (((double)nb - (double)b)*sw);
	
        circlefill(bmp, x, y, d, makecol(r, g, b)); 
}

/*** Function ***/
void makeBranch ( double start_x, double start_y, double length, double angle, double size ) {
	
	//int max_size = 8 ;
	//double branch_length = 50 ;
	
	if ( size > 0 ) {
		
		double end_x = (start_x + length * cos ( angle )) ;
		double end_y = (start_y + length * sin ( angle )) ;
		
		
		
		line(buffer, start_x, start_y, end_x, end_y, makecol(255, 0, 0));
		orig_len = line_len = sqrt(pow(end_x - start_x, 2) + pow(end_y - start_y, 2));
		//do_line(buffer, round(start_x), round(start_y), round(end_x), round(end_y), size / TRS, draw_dust_particle);
		
		double sub_branch = (rand() % (max_sub_branch - 1)) + 2 ;
		double branch_length_dimin = 0.5f + (double)(rand() % 100)/200.0f ;
		for ( int i=0; i < sub_branch; i++ ) {
			int newLength = (int)((double)length * (double)branch_length_dimin) ;
			double newAngle = angle + ((double)(rand() % 100))/100.0f * max_sub_angle - (max_sub_angle / 2.0f) ;
			float newSize = size - 3;
			//while(!key[KEY_ESC]);
			//while(!key[KEY_SPACE]);			
			makeBranch ( end_x, end_y, newLength, newAngle, newSize ) ;
		}
	}
}

void draw_tree()
{	
	clear_to_color(buffer, makecol(0, 0, 128));
	blit(buffer, screen, 0, 0, 0, 0, SC_WIDTH, SC_HEIGHT);
	textout_ex(screen, font, "Generating tree ... ", 10, 10, makecol(255, 0, 0), -1);
	printf("DRAW START\n");
	//makeBranch ( SC_WIDTH/2 - 45, SC_HEIGHT-60, branch_length*1.25, -M_PI/2.0f, max_size ) ;
	//makeBranch ( SC_WIDTH/2 + 35, SC_HEIGHT-53, branch_length*0.5, -M_PI/2.0f, max_size ) ;
	int base = rand() % 50;
	orig_len = line_len = 30+base;
	do_line(buffer, SC_WIDTH/2, SC_HEIGHT-50, SC_WIDTH/2, SC_HEIGHT-80-base, max_size / TRS, draw_dust_particle);
	makeBranch ( SC_WIDTH/2, SC_HEIGHT-80-base, branch_length, -M_PI/2.0f, max_size ) ;
	printf("DRAW END\n");
	
	blit(buffer, screen, 0, 0, 0, 0, SC_WIDTH, SC_HEIGHT);
}

int main(int argn, char * argv[])
{
	srand ( time(NULL) );
	
	
	int hwmouse = 0;
 	if(do_setup(argn, argv, &hwmouse))
 		return 1;

	/* create the display pages */
   	buffer = create_bitmap(SC_WIDTH, SC_HEIGHT);

	draw_tree();
	
	int mouse_down = 0;
	while(!key[KEY_ESC])
	{
		if(!mouse_down && (mouse_b & 1))
		{
			draw_tree();
			mouse_down = 1;
		} else if(mouse_down && !(mouse_b & 1)) {
			mouse_down = 0;
		}
	}
   	do_cleanup();
 		
 	return 0;
}
END_OF_MAIN()
